package org.liveboardgames.agricola.business;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.liveboardgames.agricola.access.ICardDao;
import org.liveboardgames.agricola.access.IGameDao;
import org.liveboardgames.agricola.business.helper.GameHelper;
import org.liveboardgames.agricola.business.updater.FarmUpdater;
import org.liveboardgames.agricola.business.updater.GameUpdater;
import org.liveboardgames.agricola.controller.AgricolaUpdateAdapter;
import org.liveboardgames.agricola.domain.Change;
import org.liveboardgames.agricola.domain.Game;
import org.liveboardgames.agricola.domain.action.Action;
import org.liveboardgames.agricola.domain.card.ImprovementCard;
import org.liveboardgames.agricola.domain.farm.Farm;
import org.liveboardgames.agricola.domain.player.Player;

public class MajorImprovementsServiceImpl implements IMajorImprovementsService {

  private IGameDao gameDao;

  private ICardDao cardDao;

  public void setGameDao(IGameDao gameDao) {
    this.gameDao = gameDao;
  }

  public void setCardDao(ICardDao cardDao) {
    this.cardDao = cardDao;
  }

  public Set<ImprovementCard> createMajorImprovements() {
    Set<ImprovementCard> majorImprovements = cardDao.getAllMajorImprovements();
    return majorImprovements;
  }

  public Set<Action> buildImprovement(Long gameId, Long playerId, Map<String, Integer> improvementCost,
      Long improvementId) {
    List<Change> changes = new ArrayList<Change>();

    GameHelper gameHelper = new GameHelper();
    Game game = gameDao.load(gameId);
    Player player = gameHelper.findPlayer(game, playerId);
    Farm farm = player.getFarm();
    ImprovementCard improvement = gameHelper.findMajorImprovement(game, improvementId);

    // Pay - by whatever means was chosen
    // TODO: pay by discarding fireplace. This needs to be passed by the UI
    FarmUpdater farmUpdater = new FarmUpdater(game, farm, changes);
    farmUpdater.pay(improvementCost);

    // Add the improvement to the player's belongings
    farmUpdater.addPlayedCard(improvement);

    // And remove it from the game's improvements
    new GameUpdater(game, changes).removeImprovement(improvement);

    // Persist the changes in DB
    gameDao.save(game);

    // Now build the output that needs to be returned to the UI
    Set<Action> additionalActions = gameHelper.getPlayTriggeredActions(improvement);
    // Update the improvement, so that the actions are now linked to the player
    // who bought the improvement
    for (Action cardAction : additionalActions) {
      // If the action does not have a target set up yet,
      // add the player
      if (cardAction.getTarget() == null) {
        cardAction.setTarget(player);
      }
    }

    new AgricolaUpdateAdapter().publishGameUpdates(gameId, changes);

    // The actions that can now be performed by the player
    return additionalActions;
  }

}
